package com.bestcem.xm.user.service.impl;

import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.common.core.enums.AuthErrorCodeEnum;
import com.bestcem.xm.common.core.enums.ReqErrorCodeEnum;
import com.bestcem.xm.component.security.dto.AuthenticationDTO;
import com.bestcem.xm.component.security.dto.TokenDTO;
import com.bestcem.xm.user.service.AuthenticationService;
import com.bestcem.xm.user.service.RolePermissionService;
import com.bestcem.xm.user.service.dto.user.AuthDTO;
import com.bestcem.xm.user.util.business.UserJwtTokenUtil;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @author Linked <zhijian.lin@idiaoyan.com>
 * @version v1.0
 * @date 2022/8/8 21:27
 */
@Slf4j
@Service
public class AuthenticationServiceImpl implements AuthenticationService {

    @Resource
    private RolePermissionService rolePermissionService;

    @Resource
    private UserJwtTokenUtil tokenUtil;

    @Override
    public ServiceResult<AuthenticationDTO> checkAuthentication(String token, Boolean authentication, String uri, String method) {
        // 校验该token是否已经退出登录
        if (tokenUtil.existJwtInvalid(token)) {
            return ServiceResult.fail(ReqErrorCodeEnum.INVALID_TOKEN, "Logged out token");
        }

        AuthDTO authDTO;
        try {
            authDTO = tokenUtil.parseToken(token);
        } catch (ExpiredJwtException e) {
            return ServiceResult.fail(AuthErrorCodeEnum.EXPIRE_TOKEN, "Token expire date.");
        } catch (Exception e) {
            return ServiceResult.fail(ReqErrorCodeEnum.INVALID_TOKEN, "Invalid Token.");
        }

        // 通过token版本号, 校验token是否过期
        if (!tokenUtil.checkTokenVersion(authDTO)) {
            return ServiceResult.fail(AuthErrorCodeEnum.EXPIRE_TOKEN, "Token expire date.");
        }

        AuthenticationDTO authenticationDTO = new AuthenticationDTO();
        if (Boolean.TRUE.equals(authentication)) {
            Boolean hasPermission = rolePermissionService.hasPermission(authDTO.getOrgId(), authDTO.getUserId(), method, uri);
            authenticationDTO.setPermission(hasPermission);
        }
        authenticationDTO.setToken(authDTOToTokenDTO(authDTO));
        return ServiceResult.success(authenticationDTO);
    }

    private TokenDTO authDTOToTokenDTO(AuthDTO authDTO) {
        TokenDTO tokenDTO = new TokenDTO();
        tokenDTO.setOrgId(authDTO.getOrgId());
        tokenDTO.setOrgCode(authDTO.getOrgCode());
        tokenDTO.setExpiredTime(authDTO.getExp());
        tokenDTO.setUserId(authDTO.getUserId());
        tokenDTO.setRealName(authDTO.getRealName());
        tokenDTO.setAvatar(authDTO.getAvatar());
        tokenDTO.setSuperRole(authDTO.getSuperRole());
        tokenDTO.setIsSenior(authDTO.getSenior());
        return tokenDTO;
    }
}
